package ch.csp.transformer;

import static org.junit.Assert.*;

import java.util.ArrayList;
import java.util.Random;

import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.experimental.categories.Categories.ExcludeCategory;

import ch.csp.exchange.ParagraphWithLines;

public class ColumnedLineTransformerTest {
	ColumnedLineTransformer transformer;

	@Before
	public void setUp() throws Exception {
		System.out.println();
		System.out.println("NEW TEST");
	}

	@Test
	public void transform_validateOk_noException() {
		ArrayList<ParagraphWithLines> paragraphsWithJustifiedLines = createParagraphs(3, 3, 3);
		transformer = new ColumnedLineTransformer(paragraphsWithJustifiedLines , 3);
		transformer.transform();
	}
	
	private ArrayList<ParagraphWithLines> createParagraphs(int amountParagraphs, int minLinesPerGraph, int maxLinesPerGraph){
		Random r = new Random();
		ArrayList<ParagraphWithLines> paragraphs = new ArrayList<ParagraphWithLines>();
		for(int i = 1; i <= amountParagraphs; i++){
			ParagraphWithLines p = new ParagraphWithLines();
			for(int j = 1; j <= createRandomInteger(minLinesPerGraph, maxLinesPerGraph, r); j++){
				p.lines.add(String.format("|Paragraph %03d, Zeile %03d|", i, j));
			}
			paragraphs.add(p);
		}
		return paragraphs;
	}
	
	private int createRandomInteger(int aStart, int aEnd, Random aRandom){
	    if (aStart > aEnd) {
	      throw new IllegalArgumentException("Start cannot exceed End.");
	    }
	    //get the range, casting to long to avoid overflow problems
	    long range = (long)aEnd - (long)aStart + 1;
	    // compute a fraction of the range, 0 <= frac < range
	    long fraction = (long)(range * aRandom.nextDouble());
	    int randomNumber =  (int)(fraction + aStart);    
	    return randomNumber;
	  }
	
	@Ignore
	@Test(expected = RuntimeException.class)
	public void transform_validateOk_exception() {
		ArrayList<ParagraphWithLines> paragraphsWithJustifiedLines = createParagraphs(3, 3, 3);
		paragraphsWithJustifiedLines.get(2).lines.add("aöslkdjföl");
		transformer = new ColumnedLineTransformer(paragraphsWithJustifiedLines , 3);
		transformer.transform();
	}
	
	@Test
	public void transform_3col3lines_lastLineOk() {
		//arrange
		int columns = 3;
		int lines = 9;
		ArrayList<ParagraphWithLines> paragraphsWithJustifiedLines = createParagraphs(1, lines, lines);
		transformer = new ColumnedLineTransformer(paragraphsWithJustifiedLines , columns);
		//act
		ArrayList<String> transformedResult = transformer.transform();
		//assert
		assertEquals("|Paragraph 001, Zeile 003|          |Paragraph 001, Zeile 006|          |Paragraph 001, Zeile 009|          ", transformedResult.get(2));
	}
	
	@Test
	public void transform_6col18lines_lastLineOk() {
		//arrange
		int columns = 6;
		int lines = 18;
		ArrayList<ParagraphWithLines> paragraphsWithJustifiedLines = createParagraphs(1, lines, lines);
		transformer = new ColumnedLineTransformer(paragraphsWithJustifiedLines , columns);
		//act
		ArrayList<String> transformedResult = transformer.transform();
		//assert
		assertEquals("|Paragraph 001, Zeile 003|          |Paragraph 001, Zeile 006|          |Paragraph 001, Zeile 009|          |Paragraph 001, Zeile 012|          |Paragraph 001, Zeile 015|          |Paragraph 001, Zeile 018|          ", transformedResult.get(2));
	}
	
	@Test
	public void transform_6col19lines_lastLineOk() {
		//arrange
		int columns = 6;
		int lines = 19;
		ArrayList<ParagraphWithLines> paragraphsWithJustifiedLines = createParagraphs(1, lines, lines);
		transformer = new ColumnedLineTransformer(paragraphsWithJustifiedLines , columns);
		//act
		ArrayList<String> transformedResult = transformer.transform();
		//assert
		assertEquals("|Paragraph 001, Zeile 004|          ", transformedResult.get(transformedResult.size() - 1));
	}
	
	@Test
	public void transform_6col20lines_lastLineOk() {
		//arrange
		int columns = 6;
		int lines = 20;
		ArrayList<ParagraphWithLines> paragraphsWithJustifiedLines = createParagraphs(1, lines, lines);
		transformer = new ColumnedLineTransformer(paragraphsWithJustifiedLines , columns);
		//act
		ArrayList<String> transformedResult = transformer.transform();
		//assert
		String expectedResult = "|Paragraph 001, Zeile 004|          |Paragraph 001, Zeile 008|          ";
		assertEquals(expectedResult, transformedResult.get(transformedResult.size() - 1));
	}
	
	@Test
	public void transform_6col21lines_lastLineOk() {
		//arrange
		int columns = 6;
		int lines = 21;
		ArrayList<ParagraphWithLines> paragraphsWithJustifiedLines = createParagraphs(1, lines, lines);
		transformer = new ColumnedLineTransformer(paragraphsWithJustifiedLines , columns);
		//act
		ArrayList<String> transformedResult = transformer.transform();
		//assert
		String expectedResult = "|Paragraph 001, Zeile 004|          |Paragraph 001, Zeile 008|          |Paragraph 001, Zeile 012|          ";
		assertEquals(expectedResult, transformedResult.get(transformedResult.size() - 1));
	}
	
	@Test
	public void transform_6col22lines_lastLineOk() {
		//arrange
		int columns = 6;
		int lines = 22;
		ArrayList<ParagraphWithLines> paragraphsWithJustifiedLines = createParagraphs(1, lines, lines);
		transformer = new ColumnedLineTransformer(paragraphsWithJustifiedLines , columns);
		//act
		ArrayList<String> transformedResult = transformer.transform();
		//assert
		String expectedResult = "|Paragraph 001, Zeile 004|          |Paragraph 001, Zeile 008|          |Paragraph 001, Zeile 012|          |Paragraph 001, Zeile 016|          ";
		assertEquals(expectedResult, transformedResult.get(transformedResult.size() - 1));
	}
	
	@Test
	public void transform_6col23lines_lastLineOk() {
		//arrange
		int columns = 6;
		int lines = 23;
		ArrayList<ParagraphWithLines> paragraphsWithJustifiedLines = createParagraphs(1, lines, lines);
		transformer = new ColumnedLineTransformer(paragraphsWithJustifiedLines , columns);
		//act
		ArrayList<String> transformedResult = transformer.transform();
		//assert
		String expectedResult = "|Paragraph 001, Zeile 004|          |Paragraph 001, Zeile 008|          |Paragraph 001, Zeile 012|          |Paragraph 001, Zeile 016|          |Paragraph 001, Zeile 020|          ";
		assertEquals(expectedResult, transformedResult.get(transformedResult.size() - 1));
	}
	
	@Test
	public void transform_6col24lines_lastLineOk() {
		//arrange
		int columns = 6;
		int lines = 24;
		ArrayList<ParagraphWithLines> paragraphsWithJustifiedLines = createParagraphs(1, lines, lines);
		transformer = new ColumnedLineTransformer(paragraphsWithJustifiedLines , columns);
		//act
		ArrayList<String> transformedResult = transformer.transform();
		//assert
		String expectedResult = "|Paragraph 001, Zeile 004|          |Paragraph 001, Zeile 008|          |Paragraph 001, Zeile 012|          |Paragraph 001, Zeile 016|          |Paragraph 001, Zeile 020|          |Paragraph 001, Zeile 024|          ";
		assertEquals(expectedResult, transformedResult.get(transformedResult.size() - 1));
	}
	
	@Test
	public void transform_6col25lines_lastLineOk() {
		//arrange
		int columns = 6;
		int lines = 25;
		ArrayList<ParagraphWithLines> paragraphsWithJustifiedLines = createParagraphs(1, lines, lines);
		transformer = new ColumnedLineTransformer(paragraphsWithJustifiedLines , columns);
		//act
		ArrayList<String> transformedResult = transformer.transform();
		//assert
		String expectedResult = "|Paragraph 001, Zeile 005|          ";
		assertEquals(expectedResult, transformedResult.get(transformedResult.size() - 1));
	}
	
	@Test
	public void transform_3cols2paragraphs_lastLineOk() {
		//arrange
		int columns = 3;
		int lines = 4;
		int paragraphs = 2;
		ArrayList<ParagraphWithLines> paragraphsWithJustifiedLines = createParagraphs(paragraphs, lines, lines);
		transformer = new ColumnedLineTransformer(paragraphsWithJustifiedLines , columns);
		//act
		ArrayList<String> transformedResult = transformer.transform();
		//assert
		assertEquals("|Paragraph 001, Zeile 003|          |Paragraph 002, Zeile 001|          |Paragraph 002, Zeile 004|          ", transformedResult.get(2));
	}
	
	@Test
	public void transform_6col6paragraphs_lastLineOk() {
		//arrange
		int columns = 6;
		int lines = 4;
		int paragraphs = 5;
		ArrayList<ParagraphWithLines> paragraphsWithJustifiedLines = createParagraphs(paragraphs, lines, lines);
		transformer = new ColumnedLineTransformer(paragraphsWithJustifiedLines , columns);
		//act
		ArrayList<String> transformedResult = transformer.transform();
		//assert
		String expectedResult = "|Paragraph 001, Zeile 004|          |Paragraph 002, Zeile 003|          |Paragraph 003, Zeile 002|          |Paragraph 004, Zeile 001|                                              |Paragraph 005, Zeile 004|          ";
		assertEquals(expectedResult, transformedResult.get(transformedResult.size() - 1));
	}
	
	@Test
	public void transform_noLines_lastLineOk() {
		//arrange
		int columns = 6;
		int lines = 0;
		int paragraphs = 5;
		ArrayList<ParagraphWithLines> paragraphsWithJustifiedLines = createParagraphs(paragraphs, lines, lines);
		transformer = new ColumnedLineTransformer(paragraphsWithJustifiedLines , columns);
		//act
		ArrayList<String> transformedResult = transformer.transform();
		//assert
		String expectedResult = "                                        ";
		assertEquals(expectedResult, transformedResult.get(transformedResult.size() - 1));
	}
	
	@Test
	public void transform_noParagraphs_lastLineOk() {
		//arrange
		int columns = 6;
		int lines = 0;
		int paragraphs = 0;
		ArrayList<ParagraphWithLines> paragraphsWithJustifiedLines = createParagraphs(paragraphs, lines, lines);
		transformer = new ColumnedLineTransformer(paragraphsWithJustifiedLines , columns);
		//act
		ArrayList<String> transformedResult = transformer.transform();
		//assert
		assertEquals(0, transformedResult.size());
	}

}
